package ws.servlet;

import java.rmi.RemoteException;

import javax.annotation.Resource;
import javax.ws.rs.*;
import javax.ws.rs.core.*;

import org.json.*;

import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import ws.reg.*;

import common.logger.*;
import common.logger.Logger.LogLevel;
import common.servlet.AbstractResource;

@Resource
@Path("/ws")
@SuppressWarnings({"javadoc", "static-method"})
public class WebServiceResource extends AbstractResource {
	private static final String	WSDL			= "http://ibm411.cs.technion.ac.il/HW5/services/RegistrationService?wsdl";
	@SuppressWarnings("unused")
	private static final String	STUB_WSDL		= "http://84.108.165.180:9090/WSRegisteryStub/services/RegistrationServiceStub?wsdl";
	static String				wsdlEndpoint	= WSDL;

	private JSONArray searchWS(WSSearcher searcher) throws RemoteException {
		RegistrationService service = new RegistrationServiceProxy(wsdlEndpoint);
		String[] endpoints = service.getRegisteredEndpoints();
		JSONArray array = new JSONArray();
		for (String endpoint : endpoints) {
			try {
				String[] results = searcher.search(endpoint);
				if (results == null) {
					results = new String[0];
				}
				array.put(results);
			} catch (RemoteException e) {
				CompositeLogger.getInstance().log(LogLevel.WARNING, "error retrieving data from service << "
						+ endpoint);
				CompositeLogger.getInstance().log(LogLevel.WARNING, "error << " + e.getMessage());
			} catch (RuntimeException e) {
				CompositeLogger.getInstance().log(LogLevel.ERROR, "error retrieving data from service << "
						+ endpoint);
				CompositeLogger.getInstance().log(LogLevel.ERROR, "error << " + e.getMessage());
			}
		}
		return array;
	}

	private Response getResponse(WSSearcher searcher, JSONObject object) {
		try {
			WSSearcher actualSearcher = searcher.build(object);
			JSONArray array = searchWS(actualSearcher);
			return Response.ok(array).build();
		} catch (JSONException e) {
			return handleJsonException(e);
		} catch (RemoteException e) {
			CompositeLogger.getInstance()
					.log(LogLevel.WARNING,
							"error retrieving data from registery webservice << " + e.getMessage());
			return handleException(e);
		} catch (RuntimeException e) {
			return handleException(e);
		}
	}

	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public Response listServices() {
		WSSearcher searcher = new WSSearcher() {
			@Override
			public String[] search(String endpoint) throws RemoteException {
				RegistrationService service = new RegistrationServiceProxy(endpoint);
				return service.getRegisteredEndpoints();
			}

			@Override
			public WSSearcher build(JSONObject parameters) throws JSONException {
				throw new NotImplementedException();
			}
		};
		String[] results;
		try {
			results = searcher.search(wsdlEndpoint);
		} catch (RemoteException e) {
			CompositeLogger.getInstance()
					.log(LogLevel.WARNING,
							"error retrieving data from registery webservice << " + e.getMessage());
			return handleException(e);
		}
		return Response.ok(new JSONArray(results)).build();
	}

	@POST
	@Produces(MediaType.APPLICATION_JSON)
	@Path("/local")
	public Response searchLocal(JSONObject object) {
		WSSearcher searcher = new LocalSearcher();
		return getResponse(searcher, object);
	}

	@POST
	@Produces(MediaType.APPLICATION_JSON)
	@Path("/keywords")
	public Response searchKeywords(JSONArray array) {
		WSSearcher searcher = new KeywordsSearcher();
		return getResponse(searcher, new JSONObject().put("array", array));
	}
}
